﻿using System;
using System.Globalization;
using System.Linq;
using System.Security.Claims;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using System.Data;
using System.Reflection;
using System.Web.SessionState;
using app.Models;
using AmuTools;
using System.Net.Mail;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using System.Text;
using System.Text.RegularExpressions;

namespace app.Api
{
    public class ApiBase
    {
        public static bool AllowApiExemption = false; // 免检
        private Dictionary<string, object> req_param_map = new Dictionary<string, object>(); // 已处理参数的缓存
        public Controller ctx { get; set; }
        public ApiBase(Controller the_ctx)
        {
            ctx = the_ctx;
            ctx.Session["base"] = this;
        }

        #region session
        public IDENTITY UserIdentity
        {
            get
            {
                return ctx.Session["user_identity"] == null ? IDENTITY.VISITOR : (IDENTITY)ctx.Session["user_identity"];
            }
            set
            {
                ctx.Session["user_identity"] = value;
            }
        }
        public string UserName
        {
            get
            {
                return ctx.Session["user_name"] == null ? "" : ctx.Session["user_name"].ToString();
            }
            set
            {
                ctx.Session["user_name"] = value;
            }
        }
        public int UserRole
        {
            get
            {
                return ctx.Session["user_role"] == null ? (int)ROLE_TYPES.GUEST : (int)ctx.Session["user_role"];
            }
            set
            {
                ctx.Session["user_role"] = value;
            }
        }
        public string UserCode
        {
            get
            {
                return ctx.Session["user_code"] == null ? "" : ctx.Session["user_code"].ToString();
            }
            set
            {
                ctx.Session["user_code"] = value;
            }
        }
        public string Token
        {
            get
            {
                return ctx.Session["token"] == null ? "" : ctx.Session["token"].ToString();
            }
            set
            {
                ctx.Session["token"] = value;
            }
        }
        public string UserPermission
        {
            get
            {
                return ctx.Session["permission"] == null ? "" : ctx.Session["permission"].ToString();
            }
            set
            {
                ctx.Session["permission"] = value;
            }
        }
        #endregion

        #region 请求参数
        // token令牌参数
        public string req_token { get { return GetStringParam(new ReqStringParamOption { Name = "token" }); } }
        // 测试使用参数
        public bool req_exemption { get { return GetBooleanParam(new ReqBooleanParamOption { Name = "exemption", Level = REQPARAMLEVEL.FREE, DefaultValue = false }); } }
        public bool req_ignore_token { get { return GetBooleanParam(new ReqBooleanParamOption { Name = "ignore_token", Level = REQPARAMLEVEL.FREE, DefaultValue = false }); } }
        // 分页参数
        public int req_current_page { get { return GetIntParam(new ReqIntParamOption { Name = "current_page", Level = REQPARAMLEVEL.VALID, DefaultValue = 1 }); } }
        public int req_page_size { get { return GetIntParam(new ReqIntParamOption { Name = "page_size", Level = REQPARAMLEVEL.VALID, DefaultValue = 100 }); } }
        public int req_list_size { get { return GetIntParam(new ReqIntParamOption { Name = "list_size", Level = REQPARAMLEVEL.VALID, DefaultValue = 100 }); } }
        public Dictionary<string, string> req_order_by { get { return GetObjectParam<Dictionary<string, string>>(new ReqObjectParamOption<Dictionary<string, string>> { Name = "order_by" ,Level=REQPARAMLEVEL.FREE ,DefaultValue=new Dictionary<string, string>()}); } }
        // 常用公有属性  
        public int req_id { get { return GetIntParam(new ReqIntParamOption { Name = "id" }); } }
        public int req_type { get { return GetIntParam(new ReqIntParamOption { Name = "type" }); } }
        public int req_status { get { return GetIntParam(new ReqIntParamOption { Name = "status" }); } }
        public string req_name { get { return GetStringParam(new ReqStringParamOption { Name = "name", InvalidTest = val => val.Length <= 50, InvalidMessage = "姓名长度超出范围" }); } }
        public string req_username { get { return GetStringParam(new ReqStringParamOption { Name = "username", InvalidTest = val => val.Length <= 50, InvalidMessage = "用户名长度超出范围" }); } }
        public string req_password { get { return GetStringParam(new ReqStringParamOption { Name = "password", InvalidTest = val => val.Length <= 16, InvalidMessage = "密码长度超出16位" }); } }
        public string req_remark { get { return GetStringParam(new ReqStringParamOption { Name = "remark" }); } }
        public string req_title { get { return GetStringParam(new ReqStringParamOption { Name = "title", InvalidTest = val => val.Length <= 50, InvalidMessage = "标题不能超过50个字符" }); } }
        public string req_content { get { return GetStringParam(new ReqStringParamOption { Name = "content" }); } }
        public string req_phone { get { return GetStringParam(new ReqStringParamOption { Name = "phone" }); } }
        public string req_mobile_phone { get { return GetStringParam(new ReqStringParamOption { Name = "mobile_phone" }); } }
        public string req_url { get { return GetStringParam(new ReqStringParamOption { Name = "url" }); } }
        public string req_logo { get { return GetStringParam(new ReqStringParamOption { Name = "logo" }); } }
        public string req_description { get { return GetStringParam(new ReqStringParamOption { Name = "description" }); } }
        public string req_email { get { return GetStringParam(new ReqStringParamOption { Name = "email" }); } }
        public int req_role_type { get { return GetIntParam(new ReqIntParamOption { Name = "role_type" }); } }
        public int req_operation_type { get { return GetIntParam(new ReqIntParamOption { Name = "operation_type" }); } }
        public string req_value { get { return GetStringParam(new ReqStringParamOption { Name = "value" }); } }
        public int req_index { get { return GetIntParam(new ReqIntParamOption { Name = "index" }); } }
        public string req_appendix_ids { get { return GetStringParam(new ReqStringParamOption { Name = "appendix_ids" }); } }
        public bool req_excel { get { return GetBooleanParam(new ReqBooleanParamOption { Name = "excel", Level = REQPARAMLEVEL.FREE, DefaultValue = false }); } }
        public string req_begin_time { get { return GetTimeStampParam(new ReqTimeStampParamOption { Name = "begin_time", Level = REQPARAMLEVEL.FREE, DefaultValue = "" }); } }
        public string req_end_time { get { return GetTimeStampParam(new ReqTimeStampParamOption { Name = "end_time", Level = REQPARAMLEVEL.FREE, DefaultValue = "" }); } }
        #endregion

        #region 请求参数函数
        /*
            参数有三种情况
            1.参数不可缺，参数必须有效
            2.参数可缺，提供默认值，参数必须有效
            3.参数可缺可无效，提供默认值 
        */
        private T GetParamWithMap<T>(ReqParamOption<T> option, IReqParamOption Ioption)
        {
            if (req_param_map.ContainsKey(option.Name))
            {
                return (T)req_param_map[option.Name];
            }
            else
            {
                T value = GetParam<T>(option, Ioption);
                req_param_map.Add(option.Name, value);
                return value;
            }
        }
        private T GetParam<T>(ReqParamOption<T> option, IReqParamOption Ioption)
        {
            string error_prefix = "错误参数" + option.Name + ":";
            string value = ctx.Request[option.Name];
            // 首先检测是否为空值
            if (value == null || value == "undefined")
            {
                // 为空
                if (option.Level == REQPARAMLEVEL.MUST_VALID)
                {
                    ThrowStatus(option.LackStatus, error_prefix + option.LackMessage);
                }
                else
                {
                    return option.DefaultValue;
                }
            }
            else
            {
                // 不为空
                // 检测是否为正确类型
                if (Ioption.TypeTest(value))
                {
                    // 类型正确
                    // 检测是否是合法有效的值
                    if (option.InvalidTest(option.Result))
                    {
                        // 有效
                        return option.Result;
                    }
                    else
                    {
                        // 无效
                        ThrowStatus(option.InvalidStatus, error_prefix + option.InvalidMessage);
                    }
                }
                else
                {
                    // 类型错误
                    if (option.Level == REQPARAMLEVEL.FREE)
                    {
                        return option.DefaultValue;
                    }
                    else
                    {
                        ThrowStatus(option.TypeErrorStatus, error_prefix + option.TypeErrorMessage);
                    }
                }
            }
            return option.DefaultValue;
        }
        public string GetStringParam(ReqStringParamOption option)
        {
            return GetParamWithMap<string>(option, option);
        }
        public bool GetBooleanParam(ReqBooleanParamOption option)
        {
            return GetParamWithMap<bool>(option, option);
        }
        public T GetObjectParam<T>(ReqObjectParamOption<T> option)
        {
            return GetParamWithMap<T>(option, option);
        }
        public int GetIntParam(ReqIntParamOption option)
        {
            return GetParamWithMap<int>(option, option);
        }
        public double GetDoubleParam(ReqDoubleParamOption option)
        {
            return GetParamWithMap<double>(option, option);
        }
        public string GetTimeStampParam(ReqTimeStampParamOption option)
        {
            return GetParamWithMap<string>(option, option);
        }
        #endregion

        #region 返回数据、抛出错误、添加日志
        // 将一个对象转成json字符串添加到response中
        public void ResponseJson(object obj, int group_code = 0)
        {
            ctx.Response.ContentType = "application/json";
            ctx.Response.Write(G.DB.ToJson(obj, group_code));
            ctx.Response.End();
        }
        public void ResponseJson(object obj, string columns)
        {
            ctx.Response.ContentType = "application/json";
            ctx.Response.Write(G.DB.ToJson(obj, columns));
            ctx.Response.End();
        }
        // 抛出错误状态码
        public void ThrowStatus(STATUS status, string message = "")
        {
            ResponseJson(new MessageResult { status = (int)status, message = message });
            throw new ApiException();
        }
        //得到ip
        private static string GetClientIP()
        {
            HttpRequest request = HttpContext.Current.Request;
            string result = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (string.IsNullOrEmpty(result))
            {
                result = request.ServerVariables["REMOTE_ADDR"];//127.0.0.1 回送ip地址 localhost 有关
            }
            if (string.IsNullOrEmpty(result))
            {
                result = request.UserHostAddress;
            }
            return result;
        }
        //ip位置
        private static string GetIPDescQQ(string ip)
        {
            IPScaner objScan = new IPScaner();
            objScan.DataPath = System.Web.HttpContext.Current.Server.MapPath("~/qqwry.dat");
            objScan.IP = ip;
            return objScan.IPLocation();
        }
        // 添加日志
        public void RecordLog(string operation, string description = "")
        {
            G.DB.Insert<Log>(new Log
            {
                role_type = UserRole,
                user_id = UserCode,
                username = UserName,
                ip = GetClientIP(),
                operation = operation,
                description = description,
                ip_location = GetIPDescQQ(GetClientIP()),
                create_time = DateTimeEx.GetNowTimeStamp()
            });
        }
        public void RecordLog(PERMISSIONOPERATION po, string description = "")
        {
            RecordLog(((int)po).ToString(), description);
        }
        // 发送系统消息
        public MemberMessage SendMessage(int target_id, string title, string content, int sender_id = 0)
        {
            if (sender_id == 0) sender_id = int.Parse(UserCode);
            MemberMessage mm = new MemberMessage { m_type = 0, user_id = target_id, title = title, content = content, create_time = DateTimeEx.GetNowTimeStamp(), sender_id = sender_id };
            G.DB.Insert<MemberMessage>(mm);
            LandingServer.HasNewMessage(target_id.ToString(), true);
            return mm;
        }

        public Boolean EditEmail(int type_2,string email,string name)
        {
            string title = "";
            string body = "";
            Template temp = G.DB.Get<Template>(new Cd().And("type_2 = '{0}'", type_2).And("selected = '1'").And("type_1 = 'email'").Render()).GetFirstEntity();
            Dictionary<string, object> dic = LandingServer.GetDictionary(UserCode);
            Dictionary<string, string> rplcdic = new Dictionary<string, string>();
            rplcdic.Add("name", name);
            if (temp != null)
            {
                title = temp.title;
                body = temp.content;
                Match mt;
                mt = Regex.Match(body, @"${(.*?)}");
                while (mt.Success)
                {
                    string key = mt.Groups[1].ToString();
                    mt = mt.NextMatch();
                }
                string reg = @"\$\{(.*?)\}";
                Regex r = new Regex(reg, RegexOptions.None);
                MatchCollection mc = r.Matches(body);
                if (mc.Count > 0)
                {
                    foreach (Match m in mc)
                    {
                        if (m.Value == "${code}")
                        {
                            string code = MessageHelper.GetCode();
                            string sendTime = DateTimeEx.DateTimeToTimeStamp(DateTime.Now);
                            body = body.Replace("${code}", "<a href =\"https://" + FreeValue.GetValue("website.domain") + "/#/emailAuth?id=" + UserCode + "&code=" + code + "&time=" + sendTime + "&email=" + email + "\">邮箱认证链接</a>");
                            dic["email"] = email;
                            dic["send_time"] = sendTime;
                            dic["code"] = code;
                        }
                        else
                        {
                            
                            string value = m.Value.Replace("${", "").Replace("}", "");
                            if (rplcdic.Keys.Contains(value))
                            {
                                string key = "";
                                rplcdic.TryGetValue(value,out key);
                                body = body.Replace(m.Value, key);
                            }
                            else
                            {
                                ThrowStatus(STATUS.NO_PERMISSION, "未设置变量[" + m.Value + "]");
                            }
                        }
                    }
                }
                MemberMessage mm = SendEmail( title, body , email);
                if (mm.status != 9)
                {
                    ResponseJson(new BooleanResult { value = true, message = "邮件发送成功！" });
                }
                else
                {
                    ResponseJson(new BooleanResult { value = false, message = "邮件发送失败！" });
                }
            }
            else
            {
                ThrowStatus(STATUS.NO_PERMISSION, "未设置启用模板");
            }
            return false;
        }

        public MemberMessage SendEmail(string title,string content,string email)
        {
            Email send = new Email();
            send = G.DB.Get<Email>(new Cd().And("selected = '1'").Render()).GetFirstEntity();
            if(send == null)
            {
                ThrowStatus(STATUS.NO_PERMISSION, "请联系管理员设置可用的发件邮箱");
            }
            string smtpServer = send.smtp;//指定SMTP服务器 smtp.qq.com
            int smtpPort = Convert.ToInt32(send.email_port);   //指定端口
            string emailUserName = send.email_name.Split('@')[0];//指定发件邮箱的邮箱账号，不包含@以后的部分
            string pwd = send.email_authorize_code; //指定授权码"voylpftszenwbfee";
            string mailAddress = send.email_name;    //指定发送邮件的地址

            bool status = sendTheMail(smtpServer, smtpPort, emailUserName, pwd, mailAddress, email, title, content);
            MemberMessage mm = new MemberMessage { m_type = 1, title = title, content = content, create_time = DateTimeEx.GetNowTimeStamp()};
            if (!status) mm.status = 9;
            return mm;
        }
        // 发送邮件
        public MemberMessage SendEmail(int target_id, string title, string content, string email_to = null, int sender_id = 0)
        {
            if (email_to == null) email_to = G.DB.GetById<Member>(target_id).h_email;
            if (sender_id == 0) sender_id = int.Parse(UserCode);

            Email temp = new Email();
            Cd cd = new Cd();
            cd.And("selected ='{0}'", 1);
            temp = G.DB.Get<Email>(cd.Render()).GetFirstEntity();
            if (temp == null)
            {
                ThrowStatus(STATUS.NO_PERMISSION, "请联系管理员设置可用的发件邮箱");
            }
            string smtpServer = temp.smtp;//指定SMTP服务器 smtp.qq.com
            int smtpPort = Convert.ToInt32(temp.email_port);   //指定端口
            string emailUserName = temp.email_name.Split('@')[0];//指定发件邮箱的邮箱账号，不包含@以后的部分
            string pwd = temp.email_authorize_code; //指定授权码"voylpftszenwbfee";
            string mailAddress = temp.email_name;    //指定发送邮件的地址

            bool status = sendTheMail(smtpServer, smtpPort, emailUserName, pwd, mailAddress, email_to, title, content);

            MemberMessage mm = new MemberMessage { m_type = 1, user_id = target_id, title = title, content = content, create_time = DateTimeEx.GetNowTimeStamp(), sender_id = sender_id };
            if (!status) mm.status = 9;
            G.DB.Insert<MemberMessage>(mm);
            return mm;
        }
        // 发送短信
        public MemberMessage SendSMS(int target_id, string number, string content, string username, int sender_id = 0)
        {
            //if (sender_id == 0) sender_id = int.Parse(UserCode);
            //MesHelper.SendValidateCode(req_mobile_phone, "SMS_125117326", "樊致远测试", checkCode);
            MesHelper.SendMes(number, username);
            MemberMessage mm = new MemberMessage { m_type = 2, user_id = target_id, content = content, create_time = DateTimeEx.GetNowTimeStamp(), sender_id = sender_id };
            G.DB.Insert<MemberMessage>(mm);
            return mm;
        }
        /// <summary>
        /// 自动发送邮件
        /// </summary>
        /// <param name="smtpServer">发送邮件所用服务器</param>
        /// <param name="smtpPort">端口</param>
        /// <param name="userName">发件邮箱名</param>
        /// <param name="pwd">发件邮箱密码，一般为授权码</param>
        /// <param name="mailAddress">发件邮箱地址</param>
        /// <param name="emailTo">邮件发送到的邮箱</param>
        /// <param name="theme">邮件主题</param>
        /// <param name="body">邮件内容</param>
        /// <returns></returns>
        private bool sendTheMail(string smtpServer, int smtpPort, string userName, string pwd, string mailAddress, string emailTo, string theme, string body)
        {
            try
            {
                SmtpClient _smtpClient = new SmtpClient();
                _smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;//指定电子邮件发送方式
                _smtpClient.Host = smtpServer;//指定SMTP服务器
                _smtpClient.Port = smtpPort;   //指定端口
                _smtpClient.EnableSsl = true;
                _smtpClient.Credentials = new System.Net.NetworkCredential(userName, pwd);
                MailMessage _mailMessage = new MailMessage();
                _mailMessage.From = new MailAddress(mailAddress);
                _mailMessage.To.Add(emailTo);
                _mailMessage.Subject = theme; //主题
                _mailMessage.Body = body;   //内容
                _mailMessage.BodyEncoding = System.Text.Encoding.Default;  //正文编码
                _mailMessage.IsBodyHtml = true;   //设置为HTML格式
                _mailMessage.Priority = MailPriority.High;  //设置优先级
                _smtpClient.Send(_mailMessage);
                return true;
            }catch(Exception e)
            {
                return false;
            }
            
        }
        #endregion

        #region 登入登出/检测权限
        public BooleanResult Login(IDENTITY identity)
        {
            string user_name = "";
            string user_password = HashHelper.Hash_MD5_16(req_password);
            string user_code = "";
            string user_permission = "";
            int user_role = (int)ROLE_TYPES.GUEST;
            BooleanResult br = new BooleanResult { value = false, message = "用户名或密码错误" };
            if (identity == IDENTITY.ADMIN)
            {
                Cd cd = new Cd();
                cd.And("username='{0}'", req_username);
                cd.And("password='{0}'", user_password);
                Admin admin = G.DB.Get<Admin>(cd.Render()).GetFirstEntity();
                if (admin != null)
                {
                    user_name = admin.username;
                    user_code = admin.id.ToString();
                    user_permission = admin.permission;
                    user_role = (int)ROLE_TYPES.ADMIN;
                }
            }
            else if (identity == IDENTITY.MEMBER)
            {
                Cd cd = new Cd();
                cd.And("username='{0}'", req_username);
                cd.And("password='{0}'", user_password);
                Member member = G.DB.Get<Member>(cd.Render()).GetFirstEntity<Member>();
                if (member != null)
                {
                    if (member.is_ban == 1)
                    {
                        br.message = "该账号已被封禁，请联系管理员解封";
                    }
                    else if(member.is_delete == 0)
                    {
                        user_name = member.username;
                        user_code = member.id.ToString();
                        user_permission = member.permission;
                        user_role = member.role_type;
                    }

                }
            }
            if (user_code != "")
            {
                bool force = Permission.Check(user_permission, Permission.Module(PERMISSIONMODULE.LOGIN).Operation(PERMISSIONOPERATION.EXCLUSIVE).GetCode());
                if (!force && LandingServer.GetUnitState(user_code) == LANDINGSTATE.ONLINE) ThrowStatus(STATUS.HAS_LOGIN, "正在其他地方登陆");
                UserIdentity = identity;
                UserName = user_name;
                UserRole = user_role;
                UserCode = user_code;
                Token = DateTimeEx.GetNowTimeStamp();
                UserPermission = user_permission;
                LandingServer.AddUnit(UserCode, Token);
                RecordLog(PERMISSIONOPERATION.LOGIN, UserName + "登录成功！");
                br.value = true;
                br.message = Token;
            }
            return br;
        }
        public void Logout()
        {
            LandingServer.RemoveUnit(UserCode, Token);
            ctx.Session.Contents.Remove("user_identity");
            ctx.Session.Contents.Remove("user_code");
            ctx.Session.Contents.Remove("token");
            ctx.Session.Contents.Remove("permission");
        }
        public void CheckPermission(IDENTITY identity, PermissionOperation operation = null)
        {
            if (identity != IDENTITY.VISITOR && UserIdentity == IDENTITY.VISITOR) ThrowStatus(STATUS.HASNOT_LOGIN, "您没有登录或session失效，请重新登录！");
            // 检测是否登陆，也有可能被挤下线
            if (!LandingServer.IsValid(UserCode, Token))
            {
                if (LandingServer.GetUnitState(UserCode) != LANDINGSTATE.OFFLINE)
                {
                    ThrowStatus(STATUS.FORCED_OFFLINE, "当前账号在其他设备登陆，请重新登陆！");
                }
                else
                {
                    ThrowStatus(STATUS.HASNOT_LOGIN, "您没有登录或session失效，请重新登录！");
                }
            }
            if (!HasPermission(identity, operation))
            {
                ThrowStatus(STATUS.NO_PERMISSION, "您没有访问权限" + (operation == null ? "" : string.Format("，权限名称：{0}，权限码：{1}", operation.GetName(), operation.GetCode())));
                return;
            }
        }
        public bool HasPermission(IDENTITY identity, PermissionOperation operation)
        {
            // 免检，用于测试
            if (AllowApiExemption && req_exemption == true) return true;

            // 解析token
            if (!req_ignore_token)
            {
                if (req_token != Token) return false;
            }

            // 检测是否登陆，也有可能被挤下线
            if (!LandingServer.IsValid(UserCode, Token)) return false;
            LandingServer.UpdateUnit(UserCode, Token); // 每次请求说明用户还扔在线，更新最后一次请求的时间

            // 检测身份
            if (identity == IDENTITY.VISITOR || identity == IDENTITY.ALL) return true;
            if (UserIdentity != identity) return false;

            // 检测权限
            if (operation == null) return true; // 如果operation为null，则不需要检测权限
            if (Permission.Check(UserPermission, operation.GetCode())) return true;
            else return false;
        }
        public bool HasPermission(IDENTITY identity)
        {
            return HasPermission(identity, null);
        }
        // 仅仅检测是否有权限，不考虑是否登陆问题
        public bool HasPermission(IDENTITY identity, string code, PermissionOperation operation)
        {
            // 检测权限
            if (operation == null) return true; // 如果operation为null，则不需要检测权限
            string permission = "";
            if (identity == IDENTITY.ADMIN) permission = G.DB.GetById<Admin>(code).permission;
            else if (identity == IDENTITY.MEMBER) permission = G.DB.GetById<Member>(code).permission;
            if (Permission.Check(permission, operation.GetCode())) return true;
            else return false;
        }
        #endregion

        #region list、分页
        public PageResult<T> GetPageResult<T>(string condition, string orderby_column) where T : class, new()
        {
            int current_page = req_current_page;
            int page_size = req_page_size;
            int total = G.DB.GetCount<T>(condition);
            int skip = (current_page - 1) * page_size;
            int take = page_size;
            Dictionary<string, string> order_by = req_order_by;
            Ob ob = new Ob();
            foreach (string key in order_by.Keys)
            {
                if (order_by[key] == "desc") ob.Desc(key);
                else if (order_by[key] == "asc") ob.Asc(key);
            }
            if (ob.Count > 0) orderby_column = ob.Render();
            List<T> list = G.DB.GetPage<T>(condition, orderby_column, skip, take).GetFirstTableList<T>();
            return new PageResult<T> { page = new PageData<T> { current_page = current_page, page_size = page_size, total = total, list = list } };
        }
        public PageResult<T> GetPageResult<T>(Cd cd, Ob ob) where T : class, new()
        {
            return GetPageResult<T>(cd.Render(), ob.Render());
        }
        public PageResult GetPageTableResult<T>(string condition, string orderby_column) where T : class, new()
        {
            return GetPageResult(G.DB.GetTableName<T>(), condition, orderby_column);
        }
        public PageResult GetPageTableResult<T>(Cd cd, Ob ob) where T : class, new()
        {
            return GetPageTableResult<T>(cd.Render(), ob.Render());
        }
        public PageResult GetPageResult(string commond, string condition, string orderby_column)
        {
            Dictionary<string, string> order_by = req_order_by;
            int current_page = req_current_page;
            int page_size = req_page_size;
            int total = G.DB.GetCount( commond, condition);
            int skip = (current_page - 1) * page_size;
            int take = page_size;
            Ob ob = new Ob();
            foreach (string key in order_by.Keys)
            {
                if (order_by[key] == "desc") ob.Desc(key);
                else if (order_by[key] == "asc") ob.Asc(key);
            }
            if (ob.Count > 0) orderby_column = ob.Render();
            object list = G.DB.GetPage(commond, condition, orderby_column, skip, take).FirstTable;
            return new PageResult { page = new PageData { current_page = current_page, page_size = page_size, total = total, list = list } };
        }
        public ListResult<T> GetListResult<T>(string condition, string orderby_column = "") where T : class, new()
        {
            List<T> list = G.DB.Get<T>(condition, orderby_column, req_list_size).GetFirstTableList<T>();
            return new ListResult<T> { list = list };
        }
        public SqlResult<T> GetSqlResult<T>(string condition, string orderby_column = "") where T : class, new()
        {
            Dictionary<string, string> order_by = req_order_by;
            Ob ob = new Ob();
            foreach (string key in order_by.Keys)
            {
                if (order_by[key] == "desc") ob.Desc(key);
                else if (order_by[key] == "asc") ob.Asc(key);
            }
            if (ob.Count > 0) orderby_column = ob.Render();
            return G.DB.Get<T>(condition, orderby_column, 0);
        }
        public void ResponseExcel(DataTable dt, Dictionary<string, string> columns, Dictionary<string, Func<object, object>> columns_handle = null)
        {
            columns_handle = columns_handle == null ? new Dictionary<string, Func<object, object>>() : columns_handle;

            //新建一个 Excel 工作簿
            ExcelPackage package = new ExcelPackage();

            // 添加一个 sheet 表
            ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(dt.TableName);

            int rowIndex = 1;   // 起始行为 1
            int colIndex = 1;   // 起始列为 1

            //设置列名
            foreach (string key in columns.Keys)
            {
                worksheet.Cells[rowIndex, colIndex].Value = columns[key];

                //自动调整列宽，也可以指定最小宽度和最大宽度
                worksheet.Column(colIndex).AutoFit();
                colIndex++;
            }
            colIndex = 1;
            //for (int i = 0; i < dt.Columns.Count; i++)
            //{
            //    worksheet.Cells[rowIndex, colIndex + i].Value = dt.Columns[i].ColumnName;

            //    //自动调整列宽，也可以指定最小宽度和最大宽度
            //    worksheet.Column(colIndex + i).AutoFit();
            //}

            // 跳过第一列列名
            rowIndex++;

            //写入数据
            Func<object, object> handle = null;
            foreach (string key in columns.Keys)
            {
                handle = columns_handle.ContainsKey(key) ? columns_handle[key] : value => { return value; };
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    worksheet.Cells[rowIndex + i, colIndex].Value = handle(dt.Rows[i][key]).ToString();

                    //自动调整行高
                    worksheet.Row(rowIndex + i).CustomHeight = true;
                }
                colIndex++;
            }
            //colIndex = 1;

            //设置字体，也可以是中文，比如：宋体
            worksheet.Cells.Style.Font.Name = "Arial";

            //字体加粗
            //worksheet.Cells.Style.Font.Bold = true;

            //字体大小
            worksheet.Cells.Style.Font.Size = 12;

            //字体颜色
            worksheet.Cells.Style.Font.Color.SetColor(System.Drawing.Color.Black);

            //单元格背景样式，要设置背景颜色必须先设置背景样式
            worksheet.Cells.Style.Fill.PatternType = ExcelFillStyle.Solid;
            //单元格背景颜色
            //worksheet.Cells.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.DimGray);

            //设置单元格所有边框样式和颜色
            worksheet.Cells.Style.Border.BorderAround(ExcelBorderStyle.Thin, System.Drawing.ColorTranslator.FromHtml("#0097DD"));

            //单独设置单元格四边框 Top、Bottom、Left、Right 的样式和颜色
            //worksheet.Cells.Style.Border.Top.Style = ExcelBorderStyle.Thin;
            //worksheet.Cells.Style.Border.Top.Color.SetColor(System.Drawing.Color.Black);

            //垂直居中
            worksheet.Cells.Style.VerticalAlignment = ExcelVerticalAlignment.Center;

            //水平居中
            //worksheet.Cells.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;

            //单元格是否自动换行
            worksheet.Cells.Style.WrapText = false;

            //设置单元格格式为文本
            worksheet.Cells.Style.Numberformat.Format = "@";

            //单元格自动适应大小
            //worksheet.Cells.Style.ShrinkToFit = true;


            ////第一种保存方式
            //string path1 = HttpContext.Current.Server.MapPath("Export/");
            //string filePath1 = path1 + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".xlsx";
            //FileStream fileStream1 = new FileStream(filePath1, FileMode.Create);
            ////保存至指定文件
            //FileInfo fileInfo = new FileInfo(filePath1);
            //package.SaveAs(fileInfo);

            ////第二种保存方式
            //string path2 = HttpContext.Current.Server.MapPath("Export/");
            //string filePath2 = path2 + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".xlsx";
            //FileStream fileStream2 = new FileStream(filePath2, FileMode.Create);
            ////写入文件流
            //package.SaveAs(fileStream2);


            //创建一个内存流，然后转换为字节数组，输出到浏览器下载
            //MemoryStream ms = new MemoryStream();
            //package.SaveAs(ms);
            //byte[] bytes = ms.ToArray();

            //也可以直接获取流
            //Stream stream = package.Stream;

            //也可以直接获取字节数组
            byte[] bytes = package.GetAsByteArray();

            //调用下面的方法输出到浏览器下载
            HttpResponse response = HttpContext.Current.Response;

            response.Buffer = true;

            response.Clear();
            response.ClearHeaders();
            response.ClearContent();

            //response.ContentType = "application/ms-excel";
            response.ContentType = "application/vnd.openxmlformats - officedocument.spreadsheetml.sheet";
            response.AppendHeader("Content-Type", "text/html; charset=GB2312");
            response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")));

            response.Charset = "GB2312";
            response.ContentEncoding = Encoding.GetEncoding("GB2312");

            response.BinaryWrite(bytes);
            response.Flush();

            response.End();

            worksheet.Dispose();
            package.Dispose();
        }
        #endregion
    }

    class ApiError : ApiBase
    {
        public ApiError(Controller ctx) : base(ctx)
        {
        }

        public void ErrorUrl(string id)
        {
            ResponseJson(new MessageResult { status = (int)STATUS.NO_RESOURCES, message = "错误路径" + id + ": 无效的api路径" });
        }

        public void HasException(Exception e)
        {
            ResponseJson(new MessageResult { status = (int)STATUS.NO_RESOURCES, message = "程序异常: " + e.Message });
        }
    }
}